#pragma once
#include <iostream>
#include <string>
#include <vector>
#include <list>
#include "JInOutPut.h"

class JSerialize
{
public:
	virtual int Serialize(JInOutPut& strea,int& allSize) = 0;
        static void SerializeHead(JInOutPut& strea,int& selfSize,int& classSize)
        {
            JSerialize::PutInt(strea,classSize,selfSize);
        }
        //返回selfSize
        static int SerializeTail(JInOutPut& strea,int& allSize,int& selfSize,int& classSize)
        {
            selfSize += classSize;
            JSerialize::Verify(strea,classSize,-1*selfSize);
            allSize += selfSize;
            return selfSize;
        }
        
	virtual int ReSerialize(JInOutPut& strea) = 0;
        static int ReSerializeHead(JInOutPut& strea)
        {
            return JSerialize::GetInt(strea,sizeof(int));
        }
	JSerialize(void);
	~JSerialize(void);
	static std::iostream& InitStream(std::string fileName);

	static int PutChars(JInOutPut& strea,const char* c,int n,int& allSize);
	//return its' self size.
	static int PutInt(JInOutPut& strea,int i,int& allSize);
	//return its' self size.
	static int Serialize(JInOutPut& strea,int i,int& allSize);
	//return its' self size.
	static int Serialize(JInOutPut& strea,std::string s,int& allSize);
	//return its' self size.
	static int Serialize(JInOutPut& strea,std::vector<int> vec,int& allSize);
	//
	static int Serialize(JInOutPut& _strea,std::list<std::string> strList,int& allSize);
	//
	template <class T>
	static int Serialize(JInOutPut& _strea,std::list<T> listT,int& allSize)
	{
		int classSize = 0;
		int selfSize = 0;
		PutInt(_strea,listT.size(),selfSize);
		typename std::list<T>::iterator ite = listT.begin();
		for(;ite != listT.end(); ++ite)
		{
			ite->Serialize(_strea,classSize);
		}
		selfSize += classSize;
		allSize += selfSize;
		return selfSize;
	}
	static int Serialize( JInOutPut& _strea,std::fstream& _fs,int& _allSize );
	//change "_offSize" data as "_data", then move pointer to cur
	static void Verify(JInOutPut& _strea,int _data,int _offSize);
	//return the int that get
	static int GetInt(JInOutPut& _strea,int intSize);

	//
	static std::string ReSerializeString(JInOutPut& _strea);

	static int ReSerializeInt(JInOutPut& strea);

	static std::vector<int> ReSerializeIntArray(JInOutPut& strea);

	static std::list<std::string> ReSerializeStringList(JInOutPut& strea);

	template <class T>
	static std::list<T> ReSerializeList(JInOutPut& _strea)
	{
            std::list<T> listT;
            int listSize = GetInt(_strea,sizeof(int));
            for(int i = 0;i < listSize; ++i)
            {
        	T t;
		t.ReSerialize(_strea);
		listT.push_back(t);
            }
            return listT;
	}

	static void ReSerializeFstream(JInOutPut& _strea,std::fstream& _fs);
};

